package yl.hs.bmipfull.service.finance.impl;

import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import yl.hs.bmipfull.daos.finance.ISettleAdditionDao;
import yl.hs.bmipfull.daos.finance.ISettleOrderDao;
import yl.hs.bmipfull.daos.finance.IShipFreightSettleDetailDao;
import yl.hs.bmipfull.daos.finance.IShipFreightSettleMainDao;
import yl.hs.bmipfull.pojo.finance.*;
import yl.hs.bmipfull.pojo.production.ProductShipOrderEntity;
import yl.hs.bmipfull.pojo.salemanage.ProductPricesEntity;
import yl.hs.bmipfull.pojo.system.UserInfoEntity;
import yl.hs.bmipfull.service.finance.IShipFreightSettleService;
import yl.hs.bmipfull.utils.CK;
import yl.hs.bmipfull.utils.HsApp;
import yl.hs.bmipfull.utils.SearchFilterEngine;
import yl.hs.bmipfull.utils.Tl;
import yl.hs.bmipfull.viewmodels.PageQuery;
import yl.hs.bmipfull.viewmodels.PageResult;
import yl.hs.bmipfull.viewmodels.SubmitModel;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/*
 * ShipFreightSettleServiceImpl
 * @category
 * @author 谢景广
 * @date 2022-08-03
 */
@Service
public class ShipFreightSettleServiceImpl extends FinanceService implements IShipFreightSettleService {
    @Override
    public PageResult<Map<String, Object>> queryPage(PageQuery query, int rowNum, Integer page) throws Exception {
        PageResult<Map<String,Object>>  result;
        query.checkSortSides(ProductShipOrderEntity.class);
        var filters = SearchFilterEngine.generateQueryList(query.getFilters(), ProductShipOrderEntity.class);
        List<Map<String,Object>> data = new ArrayList<>();
        if(rowNum>0){
            result = new PageResult<>(rowNum);
            query.getQuery().put("querySkip", (page - 1) * rowNum);
            query.getQuery().put("pageSize", rowNum);
            result.setRecords(settleMainDaoDao.queryCountByCondition(query.getQuery(),filters));
            result.setPage(page);
            var list = settleMainDaoDao.queryPage(query.getQuery(),filters);
            for (int i = 0; i < list.size(); i++) {
                var item = list.get(i);
                data.add(Tl.toMap(item));
            }
            result.setData(data);
        }
        else{
            if(query.getQuery().get("productCateSN") == null) {
                throw new Exception("搜索条件中缺少productCateSN");
            }
            var searchQuery = query.getQuery();
            if(query.getFilters()!=null && query.getFilters().size()>0){
                var startTimeOpt = query.getFilters().stream().filter(t->t.getField().equals("startTime")).findFirst();
                var endTimeOpt = query.getFilters().stream().filter(t->t.getField().equals("endTime")).findFirst();
                if(!startTimeOpt.isEmpty()){
                    searchQuery.put("startTime",startTimeOpt.get().getSearchVal());
                }
                if(!endTimeOpt.isEmpty()){
                    searchQuery.put("endTime",endTimeOpt.get().getSearchVal());
                }
            }
            var orderList = settleMainDaoDao.queryTempSettleOrders(searchQuery,filters);
            searchQuery.put("dutySN",HsApp.getSystemSet(CK.DriverDutySN));
           // var driverList = settleMainDaoDao.querySettleDrivers(searchQuery,filters);
            var driverList = new ArrayList<UserInfoEntity>();
            var tGroup = orderList.stream().collect(Collectors.groupingBy(ProductShipOrderEntity::getTruckSN,
                    Collectors.groupingBy(ProductShipOrderEntity::getTruckCode,Collectors.groupingBy(ProductShipOrderEntity::getTruckPlate))));
            for (var s: tGroup.keySet()){
                var cGroup = tGroup.get(s);
                for (var c : cGroup.keySet()){
                    var pGroup = cGroup.get(c);
                    for (var p: pGroup.keySet()){
                        driverList.add(new UserInfoEntity(s,"["+c+"]"+p));
                    }
                }
            }


            //var orderDriverSN = orderList.stream().collect(Collectors.groupingBy(ProductShipOrderEntity::getDriverSN)).entrySet().stream().map(t->t.getKey()).toList();
            //driverList = driverList.stream().filter(t->orderDriverSN.contains(t.getSn())).collect(Collectors.toList());
            var driverSettleLast = settleMainDaoDao.queryDriverSettleLast(searchQuery,filters);
            //var settlePayedList = settleMainDaoDao.queryContractReceiptList(searchQuery);//收款信息
            result = new PageResult<>(driverList.size()>0?driverList.size():1);
            result.setRecords(driverList.size());
            result.setPage(page==null?1:page);
            for (int i = 0; i < driverList.size(); i++) {
                ShipFreightSettleMainEntity item = new ShipFreightSettleMainEntity();
                var driver = driverList.get(i);
                item.setSn(driver.getSn());
                var orders = orderList.stream().filter(t->driver.getSn().equals(t.getTruckSN())).collect(Collectors.toList());
                item.setDriverSN(driver.getSn());
                item.setDriverName(driver.getRealname());
                item.setSettleTime(new Date());
                Date min,max;
                var searchStart = query.getQuery().get("startTime");
                var searchEnd = query.getQuery().get("endTime");
                var dataParse = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                if(searchStart == null || "".equals(searchStart)){
                    if(orders.size()>0) {
                        min = orders.stream().filter(t->t.getOutTime()!=null).map(ProductShipOrderEntity::getOutTime).min(Date::compareTo).get();
                    }
                    else
                        min = new Date();
                }
                else{
                    min =dataParse.parse(searchStart.toString());
                }
                if(searchEnd == null || "".equals(searchEnd)){
                    if(orders.size()>0) {
                        max = orders.stream().filter(t->t.getOutTime()!=null).map(ProductShipOrderEntity::getOutTime).max(Date::compareTo).get();
                    }
                    else
                        max = new Date();
                }
                else{
                    max = dataParse.parse(searchEnd.toString());
                }
                item.setStartTime(min);
                item.setEndTime(max);
                var lastSettle = driverSettleLast.stream().filter(t->t.getDriverSN().equals(driver.getSn())).findFirst();
                BigDecimal previousAmount=BigDecimal.ZERO,
                        totalPayedAmount=BigDecimal.ZERO,
                        currentPayedAmount=BigDecimal.ZERO,
                        totalAmount=BigDecimal.ZERO,
                        currentAmount=BigDecimal.ZERO,
                        unAAmount=BigDecimal.ZERO,//已审核未结算
                        unAmount=BigDecimal.ZERO;//未审核未结算
                int totalOrderCount = 0,currentOrderCount=0,unAOrderCount=0,unOrderCount=0;

                if(!lastSettle.isEmpty()){
                    var last = lastSettle.get();
                    previousAmount = last.getCurrentAmount();
                    totalPayedAmount = last.getTotalPayedAmount();
                    totalAmount = last.getTotalAmount();
                    totalOrderCount = last.getTotalOrderCount();
                }
                var maxOpt  = orders.stream().max(Comparator.comparing(ProductShipOrderEntity::getOutTime));
                if(maxOpt.isPresent()) {
                    item.setStartTime(maxOpt.get().getOutTime());
                }
                var minOpt  = orders.stream().max(Comparator.comparing(ProductShipOrderEntity::getOutTime));
                if(minOpt.isPresent()) {
                    item.setEndTime(minOpt.get().getOutTime());
                }
                for (int j = 0; j < orders.size(); j++) {
                    var order = orders.get(j);
                    if(order.getFreightState() ==1) {//已审核
                        if(order.getOutTime().compareTo(max)<=0){//参与结算
                            currentAmount = currentAmount.add(order.getFreightReviewAmount());
                            currentOrderCount ++;
                        }
                        else //不参与结算
                        {
                            unAAmount = unAAmount.add(order.getFreightAmount()==null?BigDecimal.ZERO:(order.getFreightAmount().add(order.getTurnSiteFreight())));
                            unAOrderCount++;
                        }
                    }
                    else if(order.getState()>=1 && order.getFreightState() ==0) {
                        unAmount = unAmount.add(order.getFreightAmount()==null?BigDecimal.ZERO:(order.getFreightAmount().add(order.getTurnSiteFreight())));
                        unOrderCount++;
                    }
                }
//                var contractReceiptAmountObj = settleReceiptList.stream().filter(t->cti.getSn().equals(t.getSn())).findFirst();
//                if(!contractReceiptAmountObj.isEmpty()){
//                    currentPayedAmount = contractReceiptAmountObj.get().getAmount();
//                    totalPayedAmount = totalPayedAmount.add(currentPayedAmount);
//                }
                item.setProductCateSN(query.getQuery().get("productCateSN").toString());
                item.setPreviousAmount(previousAmount);
                item.setCurrentAmount(currentAmount);
                item.setTotalAmount(totalAmount.add(currentAmount));
                item.setTotalPayedAmount(totalPayedAmount);
                item.setCurrentPayedAmount(currentPayedAmount);
                item.setCurrentOrderCount(currentOrderCount);
                item.setTotalOrderCount(totalOrderCount + currentOrderCount);
                item.setRemark("");
                item.setState((short) 1);
                item.setTags("truck");
                var dataMap = Tl.toMap(item);
                dataMap.put("unSettleApprovedAmount",unAAmount);
                dataMap.put("unSettleApprovedOrderCount",unAOrderCount);
                dataMap.put("unApprovedAmount",unAmount);
                dataMap.put("unApprovedOrderCount",unOrderCount);
                data.add(dataMap);
            }
            result.setData(data);
        }
        return result;
    }

    @Override
    public Map<String, Object> querySettleDetailsBySettleSN(String settleSN) {
        Map<String,Object> result = new HashMap<>();
        result.put("details", settleDetailDao.queryDetailBySettleSN(settleSN));
        result.put("additions",additionDao.queryAdditionsBySettleSN(settleSN));
        return result;
    }

    @Override
    public List<Map<String, Object>> queryTempSettleDetails(String driverSN, String productCateSN, String startDate, String endDate) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date start = null,end=null;
        if(!Tl.isEmpty(startDate)) {
            start = sdf.parse(startDate);
        }
        if(!Tl.isEmpty(endDate)) {
            end = sdf.parse(endDate);
            Calendar   calendar = new GregorianCalendar();
            calendar.setTime(end);
            calendar.add(Calendar.SECOND,1);
            end = calendar.getTime();
        }
        var data = settleDetailDao.queryTempDetails(driverSN,productCateSN,start,end);
        List<Map<String,Object>> list = new ArrayList<>();
        for (int i = 0; i < data.size(); i++) {
            Map<String,Object> map = data.get(i).toMap();
            var oldRemark = data.get(i).getRemark();
            if (!Tl.isEmpty(oldRemark)){
                map.remove("remark");
                map.put("orderSnArray",oldRemark.split(","));
                list.add(map);
            }
        }
        return  list;
    }

    @Override
    @Transactional
    public Integer cancelSettle(String settleSN) {
        var result = settleMainDaoDao.deleteBySettleSN(settleSN);
        settleDetailDao.deleteBySettleSN(settleSN);
        additionDao.deleteBySettleSN(settleSN);
        settleMainDaoDao.changeOrderToUnSettle(settleSN);
        orderDao.deleteBySettleSN(settleSN);
        return result;
    }

    @Override
    @Transactional
    public Integer saveSettle(SubmitModel model) throws Exception {
        var result = 0;
        var settleMain = new ShipFreightSettleMainEntity();
        Tl.getChangeLog(settleMain,model.getData());
        var settleSN = queryNewSN(settleMain.getClass());
        settleMain.setSn(settleSN);
        settleMain.setSettleTime(new Date());
        settleMain.setState((short) 1);
        settleMain.setPYFieldValue();
        settleMain.setOrganizationCode(getDepartSN());
        result = settleMainDaoDao.insertNew(settleMain);
        if(result>0) {
            var detailsObj = model.getData().get("details");
            if(detailsObj!=null){
                List<Map<String,Object>> detailList = (List<Map<String, Object>>) (detailsObj);
                if(detailList.size()>0){
                    for (int i = 0; i < detailList.size(); i++) {
                        var detailMap = detailList.get(i);
                        var orderSnObj = detailMap.get("orderSnArray");
                        var detailItem = new ShipFreightSettleDetailEntity();
                        var detailSN = queryNewSN(ShipFreightSettleDetailEntity.class);
                        Tl.getChangeLog(detailItem,detailMap);
                        detailItem.setSn(detailSN);
                        detailItem.setSettleSN(settleSN);
                        var dResult = settleDetailDao.insertNew(detailItem);
                        if(orderSnObj!=null){
                            List<String> orderSNList = (List<String>) orderSnObj;
                            if(orderSNList.size()>0){
                                for (int j = 0; j < orderSNList.size(); j++) {
                                    var settleOrder = new SettleOrderEntity();
                                    settleOrder.setSettleSN(settleSN);
                                    settleOrder.setDetailSN(detailSN);
                                    settleOrder.setOrderSN(orderSNList.get(j));
                                    orderDao.insertNew(settleOrder);
                                }
                            }
                        }
                    }
                    settleMainDaoDao.changeOrderToSettled(settleSN);
                }
            }
            var additionsObj = model.getData().get("additions");
            if (additionsObj!=null){
                List<Map<String,Object>> additionList = (List<Map<String, Object>>) additionsObj;
                if(additionList.size()>0){
                    for (int i = 0; i < additionList.size(); i++) {
                        var additionItem = new SettleAdditionEntity();
                        var additionMap = additionList.get(i);
                        additionItem.setSn(queryNewSN(additionItem.getClass()));
                        Tl.getChangeLog(additionItem,additionMap);
                        additionItem.setSettleSN(settleSN);
                        additionDao.insertNew(additionItem);
                    }
                }
            }
        }
        return  result;
    }

    @Override
    public List<ProductShipOrderEntity> querySettleOrdersBySettleSN(String settleSN) {
        return settleMainDaoDao.querySettleOrdersBySettleSN(settleSN);
    }

    private IShipFreightSettleMainDao settleMainDaoDao;

    @Autowired
    public void setSettleMainDaoDao(IShipFreightSettleMainDao dao){
        this.settleMainDaoDao = dao;
    }

    private IShipFreightSettleDetailDao settleDetailDao;
    @Autowired
    public void setSettleDetailDao(IShipFreightSettleDetailDao dao){
        this.settleDetailDao = dao;
    }

    private ISettleAdditionDao additionDao;
    @Autowired
    public void setAdditionDao(ISettleAdditionDao dao){
        additionDao = dao;
    }

    private ISettleOrderDao orderDao;
    @Autowired
    public void setOrderDao(ISettleOrderDao dao){
        orderDao = dao;
    }

}
